package com.xuecheng.content.service.jobhandler;

import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.content.feignclient.CourseIndex;
import com.xuecheng.content.feignclient.SearchServiceClient;
import com.xuecheng.content.mapper.CoursePublishMapper;
import com.xuecheng.content.model.po.CoursePublish;
import com.xuecheng.content.service.CoursePublishService;
import com.xuecheng.messagesdk.model.po.MqMessage;
import com.xuecheng.messagesdk.service.MessageProcessAbstract;
import com.xuecheng.messagesdk.service.MqMessageService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;

@Component
@Slf4j
public class CoursePublishTask extends MessageProcessAbstract {

    @Autowired
    private CoursePublishService coursePublishService;
    @Autowired
    private CoursePublishMapper coursePublishMapper;
    @Autowired
    private SearchServiceClient searchServiceClient;

    //任务调度入口
    @XxlJob("CoursePublishJobHandler")
    public void coursePublishJobHandler() throws Exception {
        // 分片参数
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();
        log.debug("shardIndex="+shardIndex+",shardTotal="+shardTotal);
        //参数:分片序号、分片总数、消息类型、一次最多取到的任务数量、一次任务调度执行的超时时间
        process(shardIndex,shardTotal,"course_publish",30,60);
    }


    //在消息服务的抽象类里面的process里面调用了这个方法 因为线程里面是执行此次任务的逻辑 就像处理视频转码任务一样把转码的逻辑写在了process里面
    //MqMessage表示消息表里面的一条数据 也就是课程发布的数据
    //这里就是线程领取到任务的执行逻辑 需要对课程发布后提高搜索效率进行的处理
    @Override
    public boolean execute(MqMessage mqMessage) {
        Long courseId = Long.parseLong(mqMessage.getBusinessKey1());

        generateCourseHtml(mqMessage,courseId);

        saveCourseIndex(mqMessage,courseId);

        return true;
    }

    //生成课程静态化页面并上传至文件系统 所以静态文件就可以通过文件系统反向代理到minio直接访问文件了
    //MqMessage表示消息表里面的一条数据 也就是课程发布的数据
    public void generateCourseHtml(MqMessage mqMessage,long courseId){
        Long taskId = mqMessage.getId();
        MqMessageService mqMessageService = this.getMqMessageService();
        //实现幂等性
        int stageOne = mqMessageService.getStageOne(taskId);
        if(stageOne>0){
            log.debug("课程静态化任务完成，无需处理。。。");
            return ;
        }

        //在这里调用了课程发布实现类里面的对课程发布进行静态化的方法
        File file = coursePublishService.generateCourseHtml(courseId);
        if(file==null){
            XueChengPlusException.cast("生成的静态页面为空");
        }

        //生成静态页面的同时把静态页面上传到minio
        coursePublishService.uploadCourseHtml(courseId,file);
//        int i=1/0;

        //在这里保证幂等性 把状态修改了下次就不用在执行这个方法了 修改后所以在消息服务的抽象类里面的执行器进行领取分配的任务的时候就领取不到了 因为sql语句的限制
        mqMessageService.completedStageOne(taskId);

    }

    //保存课程索引信息
    public void saveCourseIndex(MqMessage mqMessage,long courseId){
        Long taskId = mqMessage.getId();
        MqMessageService mqMessageService = this.getMqMessageService();
        int stageTwo = mqMessageService.getStageTwo(taskId);
        if(stageTwo>0){
            log.debug("课程信息已经写入，无需处理。。。");
            return ;
        }

        CoursePublish coursePublish = coursePublishMapper.selectById(courseId);

        CourseIndex courseIndex = new CourseIndex();
        BeanUtils.copyProperties(coursePublish,courseIndex);

        Boolean add = searchServiceClient.add(courseIndex);
        if(!add){
            XueChengPlusException.cast("远程调用搜索服务添加课程索引失败");
        }


        mqMessageService.completedStageTwo(taskId);
    }
}
